#include "IncludeHeader.h"
#include "Shader11.h"

Shader::Shader()
{
	m_pVertexShader = NULL;
	m_pPixelShader = NULL;
	m_pSamplerState = NULL;
	m_pShaderResourceView = NULL;
	m_pInputLayout = NULL;
}


HRESULT Shader::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
	HRESULT hr = S_OK;

    // find the file
    WCHAR str[MAX_PATH];
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szFileName ) );

    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

    ID3DBlob* pErrorBlob;
    hr = D3DX11CompileFromFile( str, NULL, NULL, szEntryPoint, szShaderModel, 
        dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
    if( FAILED(hr) )
    {
        if( pErrorBlob != NULL )
            OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
        SAFE_RELEASE( pErrorBlob );
        return hr;
    }
    SAFE_RELEASE( pErrorBlob );

    return S_OK;
}


HRESULT Shader::CreateVertexShader(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel,const D3D11_INPUT_ELEMENT_DESC* pInputLayoutDesc,int EnlementNum)
{
	HRESULT hr = S_OK;
	ID3DBlob* pVetextShaderBuf = NULL;
	V_RETURN( CompileShaderFromFile( szFileName, szEntryPoint, szShaderModel, &pVetextShaderBuf));
	ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
	if(pd3dDevice&&pVetextShaderBuf)
	{
		V_RETURN(pd3dDevice->CreateVertexShader(pVetextShaderBuf->GetBufferPointer(),pVetextShaderBuf->GetBufferSize(),NULL,&m_pVertexShader));
	}
	if(pInputLayoutDesc == NULL)
	{
		const D3D11_INPUT_ELEMENT_DESC layout[] =
		{
			{ "POSITION",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
			{ "NORMAL",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
			{ "TEXCOORD",  0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		};

		V_RETURN( pd3dDevice->CreateInputLayout( layout, ARRAYSIZE( layout ), pVetextShaderBuf->GetBufferPointer(),
												 pVetextShaderBuf->GetBufferSize(), &m_pInputLayout ) );
	}
	else
	{
		V_RETURN( pd3dDevice->CreateInputLayout( pInputLayoutDesc, EnlementNum, pVetextShaderBuf->GetBufferPointer(),
												 pVetextShaderBuf->GetBufferSize(), &m_pInputLayout ) );
	}
	return hr;
}

HRESULT Shader::CreatePixelShader(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel,D3D11_SAMPLER_DESC* pSamplerDesc)
{
	HRESULT hr = S_OK;
	ID3DBlob* pPixelShaderBuf = NULL;
	V_RETURN( CompileShaderFromFile( szFileName, szEntryPoint, szShaderModel, &pPixelShaderBuf));
	ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
	if(pd3dDevice&&pPixelShaderBuf)
	{
		V_RETURN(pd3dDevice->CreatePixelShader(pPixelShaderBuf->GetBufferPointer(),pPixelShaderBuf->GetBufferSize(),NULL,&m_pPixelShader));
	}
	if(pSamplerDesc == NULL)
	{
		D3D11_SAMPLER_DESC SamDesc;
		SamDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
		SamDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
		SamDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
		SamDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
		SamDesc.MipLODBias = 0.0f;
		SamDesc.MaxAnisotropy = 1;
		SamDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
		SamDesc.BorderColor[0] = SamDesc.BorderColor[1] = SamDesc.BorderColor[2] = SamDesc.BorderColor[3] = 0;
		SamDesc.MinLOD = 0;
		SamDesc.MaxLOD = D3D11_FLOAT32_MAX;
		V_RETURN( pd3dDevice->CreateSamplerState( &SamDesc, &m_pSamplerState ) );
	}
	return hr;
}


HRESULT Shader::CreateVertexShaderParameters(D3D11_BUFFER_DESC* pDesc)
{
	return S_OK;
}

HRESULT Shader::CreatePixelShaderParameters(D3D11_BUFFER_DESC* pDesc)
{
	return S_OK;
}